#include "../../Base/stdafx.h"
#include "../../Base/GameEngine.h"
#include "../../Base/DXDevice.h"
#include "SkyBox.h"
#include "../../Base/Vertex.h"
#include "../../Effects/Effect.h"
#include "../../Effects/EffectLib.h"
#include <boost/foreach.hpp>
#include "../../Time/Counter.h"

SkyBox::SkyBox(const tstring& texture, float size)
{
	m_MeshDesc.ownRender = true;
	Counter mCounter;
	mCounter.Start();

	m_Effect = EFFECTLIB->CreateEffect(_T("./Shaders/SkyBox.fx"));
	m_Tech = m_Effect->GetTechniqueByName("Render");
	m_WVP = m_Effect->GetVariableBySemantic("WorldViewProjection")->AsMatrix();
	m_TexVar = m_Effect->GetVariableByName("diffuseTexture")->AsShaderResource();
	const D3D10_INPUT_ELEMENT_DESC layoutScene[] =
	{
		{ "POSITION",  0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
		{ "TEXCOORD",    0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },

	};
	UINT numElementsScene = sizeof(layoutScene)/sizeof(layoutScene[0]);
	D3D10_PASS_DESC passDesc;
	m_Tech->GetPassByIndex(0)->GetDesc(&passDesc);
	DXDEVICE->GetDevice()->CreateInputLayout(layoutScene, numElementsScene, passDesc.pIAInputSignature, passDesc.IAInputSignatureSize,  &m_Layout);

	VertexPT t_vert[20];
	//Front
	t_vert[0] = VertexPT(-size/2, size/2, size/2, 1.0f/4,1.0f/3);
	t_vert[1] = VertexPT(size/2, size/2, size/2, 2.0f/4,1.0f/3);
	t_vert[2] = VertexPT(size/2, -size/2, size/2, 2.0f/4,2.0f/3);
	t_vert[3] = VertexPT(-size/2, -size/2, size/2, 1.0f/4,2.0f/3);
	//Back
	t_vert[4] = VertexPT(size/2, size/2, -size/2, 3.0f/4,1.0f/3);
	t_vert[5] = VertexPT(-size/2, size/2, -size/2, 1.0f,1.0f/3);
	t_vert[6] = VertexPT(-size/2, -size/2, -size/2, 1.0f,2.0f/3);
	t_vert[7] = VertexPT(size/2, -size/2, -size/2, 3.0f/4,2.0f/3);
	//Left
	t_vert[8] = VertexPT(-size/2, size/2, -size/2, 0.0f,1.0f/3);
	t_vert[9] = VertexPT(-size/2, size/2, size/2, 1.0f/4,1.0f/3);
	t_vert[10] = VertexPT(-size/2, -size/2, size/2, 1.0f/4,2.0f/3);
	t_vert[11] = VertexPT(-size/2, -size/2, -size/2, 0.0f,2.0f/3);
	//Right
	t_vert[12] = VertexPT(size/2, size/2, size/2, 2.0f/4,1.0f/3);
	t_vert[13] = VertexPT(size/2, size/2, -size/2, 3.0f/4,1.0f/3);
	t_vert[14] = VertexPT(size/2, -size/2, -size/2, 3.0f/4,2.0f/3);
	t_vert[15] = VertexPT(size/2, -size/2, size/2, 2.0f/4,2.0f/3);
	//Up
	t_vert[16] = VertexPT(-size/2, size/2, -size/2, 1.0f/4,0.0f);
	t_vert[17] = VertexPT(size/2, size/2, -size/2, 2.0f/4,0.0f);
	t_vert[18] = VertexPT(size/2, size/2, size/2, 2.0f/4,1.0f/3);
	t_vert[19] = VertexPT(-size/2, size/2, size/2, 1.0f/4,1.0f/3);

	D3D10_BUFFER_DESC bd;
	bd.Usage = D3D10_USAGE_DEFAULT;
	bd.ByteWidth = sizeof( VertexPT ) * 20;
	bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
	bd.CPUAccessFlags = 0;
	bd.MiscFlags = 0;
	D3D10_SUBRESOURCE_DATA InitData;
	InitData.pSysMem = t_vert;
	DXDEVICE->GetDevice()->CreateBuffer( &bd, &InitData, &m_VertexBuffer );

	DWORD i[30];
	i[0] = 0; i[1] = 1; i[2] = 2;
	i[3] = 0; i[4] = 2; i[5] = 3;

	i[6] = 4; i[7] = 5; i[8] = 6;
	i[9] = 4; i[10] = 6; i[11] = 7;

	i[12] = 8; i[13] = 9; i[14] = 10;
	i[15] = 8; i[16] = 10; i[17] = 11;

	i[18] = 12; i[19] = 13; i[20] = 14;
	i[21] = 12; i[22] = 14; i[23] = 15;

	i[24] = 16; i[25] = 17; i[26] = 18;
	i[27] = 16; i[28] = 18; i[29] = 19;

	 bd.Usage = D3D10_USAGE_DEFAULT;
	bd.ByteWidth = sizeof( DWORD ) * 30;        // 36 vertices needed for 12 triangles in a triangle list
	bd.BindFlags = D3D10_BIND_INDEX_BUFFER;
	bd.CPUAccessFlags = 0;
	bd.MiscFlags = 0;
	InitData.pSysMem = i;
	DXDEVICE->GetDevice()->CreateBuffer( &bd, &InitData, &m_IndexBuffer );


	DXDEVICE->GetMatrixen(m_World, m_View, m_Proj);
	D3DX10CreateShaderResourceViewFromFile(DXDEVICE->GetDevice(), texture.c_str(), NULL, NULL, &m_Tex, NULL);
	// Reset default rotation
	m_DefRot = D3DXVECTOR3(0.0f, 0.0f, 0.0f);

	mCounter.Stop();
	LOG(tstring(_T("Created SkyBox. Time: ") + mCounter.GetTime()));
}

SkyBox::~SkyBox()
{
	if(m_VertexBuffer) m_VertexBuffer->Release();
	if(m_IndexBuffer) m_IndexBuffer->Release();
	if(m_Layout) m_Layout->Release();
	if(m_Tex) m_Tex->Release();
}

void SkyBox::Draw()
{
	DXDevice::GetSingleton()->GetDevice()->IASetInputLayout(m_Layout);
	UINT stride = sizeof(VertexPT);
	UINT offset = 0;

	m_WVP->SetMatrix((float*) &(m_World * m_View * m_Proj));

	DXDevice::GetSingleton()->GetDevice()->IASetVertexBuffers(0, 1, &m_VertexBuffer, &stride, &offset);
	DXDevice::GetSingleton()->GetDevice()->IASetIndexBuffer(m_IndexBuffer, DXGI_FORMAT_R32_UINT, 0);
	DXDevice::GetSingleton()->GetDevice()->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);


	D3D10_TECHNIQUE_DESC tech;
	m_Tech->GetDesc( &tech);
	m_TexVar->SetResource(m_Tex);
	for(UINT t = 0; t < tech.Passes; ++t)
	{
		
		m_Tech->GetPassByIndex(t)->Apply(0);
		DXDEVICE->GetDevice()->DrawIndexed(30, 0, 0);
	}
}

void SkyBox::Tick(float dTime)
{
	D3DXMATRIX ViewInv;
	DXDEVICE->GetMatrixen(m_View, m_Proj);
	D3DXMatrixInverse(&ViewInv, 0, &m_View);
	D3DXVECTOR3 vec(&ViewInv[3*4]);
	this->SetTranslate(vec);
	this->GetTotalTranspose();
}